Skip to content

Conversation

@schiller-manuel
Copy link
Contributor

@schiller-manuel schiller-manuel commented Jan 10, 2026

closes #6350

Summary by CodeRabbit

  • New Features

    • indexToken and routeToken now accept regex patterns as well as strings, RegExp, or JSON regex objects for more flexible route matching.
    • Improved token handling for more accurate filename/segment matching and escaping.
  • Documentation

    • Expanded file-based routing docs with detailed regex examples, escaping guidance, and concrete matching examples.

✏️ Tip: You can customize this high-level summary in your review settings.

@schiller-manuel schiller-manuel requested review from SeanCassiere and nlynzaad and removed request for SeanCassiere January 10, 2026 22:38
@github-actions github-actions bot added documentation Everything documentation related package: router-generator labels Jan 10, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 10, 2026

📝 Walkthrough

Walkthrough

This PR adds support for regex-style token matchers for indexToken and routeToken (strings, RegExp, or JSON { regex, flags }), threads precompiled token regexes through route generation, updates discovery/escaping logic, and expands docs and tests to cover regex and JSON token configurations.

Changes

Cohort / File(s) Summary
Documentation Updates
docs/router/api/file-based-routing.md, docs/router/framework/react/routing/file-naming-conventions.md
Documented regex support for routeToken/indexToken, added JSON examples, escaping guidance, and concrete filename-match examples.
Config Types & Loading
packages/router-generator/src/config.ts
Added TokenMatcher/TokenMatcherJson types and Zod schemas; replaced string-only tokens with tokenMatcherSchema; changed config merge/load order and added areTokensEqual() helper to compare token matchers.
Token Utilities
packages/router-generator/src/utils.ts
Added createTokenRegex(token, {type}), isBracketWrappedSegment(), and unwrapBracketWrappedSegment(); added token flag sanitization and support for string/RegExp/JSON token forms.
Generator: precompiled regexes
packages/router-generator/src/generator.ts
Added four precompiled regex fields (filename & segment variants for index/route tokens), initialize via createTokenRegex, and pass segment regexes into route discovery and sorting logic.
Physical route discovery
packages/router-generator/src/filesystem/physical/getRouteNodes.ts
Added exported TokenRegexBundle interface; updated signatures (getRouteNodes, getRouteMeta, isValidPathlessLayoutRoute) to accept tokenRegexes; replaced direct token checks with segment/filename regexes and bracket-unwrapping logic.
Virtual route discovery
packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
Imported TokenRegexBundle, added tokenRegexes parameter to getRouteNodes and recursive helper, and propagated tokenRegexes through recursive calls and physical node generation.
Tests & Fixtures
packages/router-generator/tests/generator.test.ts, packages/router-generator/tests/generator/regex-tokens-inline/*, packages/router-generator/tests/generator/regex-tokens-json/*, packages/router-generator/tests/generator/virtual-config-file-*/tsr.config.json
Added inline and JSON token test variants, new route fixtures and snapshots, adjusted test setup to pass optional configDirectory when tsr.config.json exists, and added test verifying absolute physicalDirectories.
Snapshots / Naming fixes
packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts, various generated snapshots
Minor renames (e.g., IndexRouteindexRoute) and added/generated routeTree snapshots for the new token scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Generator
    participant ConfigLoader
    participant TokenUtils
    participant RouteDiscovery

    User->>Generator: initialize with inline config
    Generator->>ConfigLoader: load tsr.config.json (if present) and merge
    ConfigLoader-->>Generator: merged Config with TokenMatcher tokens

    Generator->>TokenUtils: createTokenRegex(token, type:'filename'|'segment')
    TokenUtils-->>Generator: TokenRegexBundle (4 RegExp)

    Generator->>RouteDiscovery: getRouteNodes(root, tokenRegexes)
    RouteDiscovery->>RouteDiscovery: detect tokens using segment regexes
    RouteDiscovery->>TokenUtils: unwrapBracketWrappedSegment if escaped
    RouteDiscovery-->>Generator: route nodes / route tree

    Generator-->>User: built route tree
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • nlynzaad

Poem

🐰 I stitched regex threads into tokenled seams,
file names now dance in pattern-filled dreams.
Brackets unwrapped let escapes take their place,
routes find their home with clearer, kinder grace.
Hop, hop — a rabbit cheers the routing race!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main feature: adding regex support for indexToken and routeToken, directly addressing the linked issue #6350.
Linked Issues check ✅ Passed The PR implementation fully addresses issue #6350 by allowing indexToken and routeToken to accept RegExp, RegExp-like strings, and JSON regex objects through comprehensive config, type, and utility changes across the codebase.
Out of Scope Changes check ✅ Passed All changes are in scope: documentation updates, config schema extensions, regex utility additions, test fixtures for both inline and JSON regex configurations, and routing logic updates to handle the new token formats.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Jan 10, 2026

View your CI Pipeline Execution ↗ for commit 029f14a

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 18m 9s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 36s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-10 23:10:56 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 10, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6354

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@6354

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6354

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@6354

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@6354

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@6354

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@6354

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6354

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6354

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6354

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@6354

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@6354

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@6354

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@6354

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@6354

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@6354

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@6354

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@6354

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@6354

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@6354

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@6354

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@6354

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6354

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6354

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6354

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6354

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6354

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6354

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6354

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@6354

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6354

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6354

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6354

@tanstack/vue-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@6354

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@6354

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@6354

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6354

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6354

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6354

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6354

commit: 029f14a

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/router-generator/src/filesystem/virtual/getRouteNodes.ts (1)

150-171: Normalize physicalDirectories to absolute paths for consistent path matching in downstream checks.

In nested virtual-inside-physical configurations, the physicalDirectories array accumulates paths with inconsistent bases. When node.directory is relative to fullDir and physicalDirectories from getRouteNodesPhysical are relative to resolve(fullDir, node.directory), they create a mismatch. Later, in generator.ts, the check this.physicalDirectories.some((dir) => filePath.startsWith(dir)) may fail if paths aren't aligned to the same scale. Normalizing to absolute paths ensures reliable matching across nesting levels.

Proposed fix
       if (node.type === 'physical') {
         const { routeNodes, physicalDirectories } = await getRouteNodesPhysical(
           {
             ...tsrConfig,
             routesDirectory: resolve(fullDir, node.directory),
           },
           root,
           tokenRegexes,
         )
-        allPhysicalDirectories.push(node.directory, ...physicalDirectories)
+        // Normalize to absolute paths for downstream `startsWith(...)` checks
+        allPhysicalDirectories.push(
+          resolve(fullDir, node.directory),
+          ...physicalDirectories.map((d) => resolve(fullDir, d)),
+        )
         routeNodes.forEach((subtreeNode) => {
           subtreeNode.variableName = routePathToVariable(
             `${node.pathPrefix}/${removeExt(subtreeNode.filePath)}`,
           )
🧹 Nitpick comments (5)
packages/router-generator/src/config.ts (1)

208-231: Consider whether semantically equivalent tokens should be detected.

The areTokensEqual function compares tokens strictly by form (string vs RegExp vs JSON object). A user could bypass the equality check by specifying semantically equivalent tokens in different forms (e.g., indexToken: "index" and routeToken: { regex: "^index$" }).

This may be intentional—if so, no action needed. Otherwise, consider normalizing tokens to a common form before comparison.

packages/router-generator/src/filesystem/physical/getRouteNodes.ts (2)

261-268: Escape special regex characters in segment before constructing RegExp.

The stripSegment variable comes from file path segments which could contain regex metacharacters (e.g., $, ., (, )). While the static analysis ReDoS warning is low-risk since this is filesystem input, unescaped metacharacters could cause unexpected matching behavior.

Proposed fix: escape regex metacharacters
+ const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+
  if (suffixToStrip || shouldStripRouteToken) {
    const stripSegment = suffixToStrip ?? lastRouteSegment
-   routePath = routePath.replace(new RegExp(`/${stripSegment}$`), '')
+   routePath = routePath.replace(new RegExp(`/${escapeRegex(stripSegment)}$`), '')
    originalRoutePath = originalRoutePath.replace(
-     new RegExp(`/${stripSegment}$`),
+     new RegExp(`/${escapeRegex(stripSegment)}$`),
      '',
    )
  }

Alternatively, use string methods like endsWith + slice to avoid regex entirely.


301-312: Same regex escaping concern applies here.

The updatedLastRouteSegment and indexTokenCandidate variables should also be escaped when used in RegExp constructors, or replaced with string-based suffix removal.

Proposed fix
+ const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+
  routePath =
    routePath.replace(
-     new RegExp(`/${updatedLastRouteSegment}$`),
+     new RegExp(`/${escapeRegex(updatedLastRouteSegment)}$`),
      '/',
    ) || (isLayoutRoute ? '' : '/')

  originalRoutePath =
    originalRoutePath.replace(
-     new RegExp(`/${indexTokenCandidate}$`),
+     new RegExp(`/${escapeRegex(indexTokenCandidate)}$`),
      '/',
    ) || (isLayoutRoute ? '' : '/')
packages/router-generator/tests/generator.test.ts (1)

51-62: Consider always passing the fixture folder as configDirectory to keep tests hermetic.

packages/router-generator/src/generator.ts (1)

195-242: Good split of filename-vs-segment regexes; ensure segment regexes aren’t stateful (g/y) since you call .test.

(If createTokenRegex sanitizes g/y, this is fully addressed.)
Optionally: once sanitized, consider swapping .match(...) to .test(...) to avoid allocations.

Also applies to: 362-375, 394-401, 584-597

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fad5fdb and ece084f.

📒 Files selected for processing (24)
  • docs/router/api/file-based-routing.md
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/src/config.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/src/utils.ts
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • packages/router-generator/tests/generator/virtual-config-file-default-export/tsr.config.json
  • packages/router-generator/tests/generator/virtual-config-file-named-export/tsr.config.json
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
🧰 Additional context used
📓 Path-based instructions (3)
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

Use relative links to docs/ folder format (e.g., ./guide/data-loading) for internal documentation references

Files:

  • docs/router/framework/react/routing/file-naming-conventions.md
  • docs/router/api/file-based-routing.md
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/src/config.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/src/utils.ts
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/src/config.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/src/utils.ts
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
🧠 Learnings (12)
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/virtual-config-file-named-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/src/config.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/tests/generator/virtual-config-file-default-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/src/utils.ts
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/virtual-config-file-named-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/src/config.ts
  • docs/router/api/file-based-routing.md
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/tests/generator/virtual-config-file-default-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/src/utils.ts
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.

Applied to files:

  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/virtual-config-file-named-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/src/config.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/tests/generator/virtual-config-file-default-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
📚 Learning: 2025-12-17T02:17:55.086Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:55.086Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.

Applied to files:

  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/virtual-config-file-named-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/src/config.ts
  • docs/router/api/file-based-routing.md
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/virtual-config-file-default-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions

Applied to files:

  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • docs/router/api/file-based-routing.md
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
📚 Learning: 2025-12-21T12:52:35.231Z
Learnt from: Sheraff
Repo: TanStack/router PR: 6171
File: packages/router-core/src/new-process-route-tree.ts:898-898
Timestamp: 2025-12-21T12:52:35.231Z
Learning: In `packages/router-core/src/new-process-route-tree.ts`, the matching logic intentionally allows paths without trailing slashes to match index routes with trailing slashes (e.g., `/a` can match `/a/` route), but not vice-versa (e.g., `/a/` cannot match `/a` layout route). This is implemented via the condition `!pathIsIndex || node.kind === SEGMENT_TYPE_INDEX` and is a deliberate design decision to provide better UX by being permissive with missing trailing slashes.

Applied to files:

  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/src/config.ts
  • docs/router/api/file-based-routing.md
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/src/utils.ts
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
📚 Learning: 2025-09-28T21:41:45.233Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5284
File: e2e/react-start/basic/server.js:50-0
Timestamp: 2025-09-28T21:41:45.233Z
Learning: In Express v5, catch-all routes must use named wildcards. Use `/*splat` to match everything except root path, or `/{*splat}` (with braces) to match including root path. The old `*` syntax is not allowed and will cause "Missing parameter name" errors. This breaking change requires explicit naming of wildcard parameters.

Applied to files:

  • docs/router/framework/react/routing/file-naming-conventions.md
  • docs/router/api/file-based-routing.md
📚 Learning: 2025-10-14T18:59:33.990Z
Learnt from: FatahChan
Repo: TanStack/router PR: 5475
File: e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx:8-0
Timestamp: 2025-10-14T18:59:33.990Z
Learning: In TanStack Router e2e test files, when a route parameter is validated at the route level (e.g., using zod in validateSearch or param validation), switch statements on that parameter do not require a default case, as the validation ensures only expected values will reach the switch.

Applied to files:

  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
📚 Learning: 2025-09-22T00:56:49.237Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5182
File: e2e/react-router/basic-file-based/src/routes/non-nested/named/$baz_.bar.tsx:3-5
Timestamp: 2025-09-22T00:56:49.237Z
Learning: In TanStack Router, underscores are intentionally stripped from route segments (e.g., `$baz_` becomes `baz` in generated types) but should be preserved in base path segments. This is the correct behavior as of the fix in PR #5182.

Applied to files:

  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
📚 Learning: 2025-10-01T18:30:26.591Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.

Applied to files:

  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
📚 Learning: 2025-09-22T00:56:53.426Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5182
File: e2e/react-router/basic-file-based/tests/non-nested-paths.spec.ts:167-172
Timestamp: 2025-09-22T00:56:53.426Z
Learning: In TanStack Router, underscores are intentionally stripped from route segments during path parsing, but preserved in base path segments. This is the expected behavior implemented in PR #5182.

Applied to files:

  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
📚 Learning: 2025-12-17T02:17:47.423Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:47.423Z
Learning: In packages/router-generator/src/generator.ts, enforce that pathless_layout routes with a cleanedPath must have a path property. This is required because child routes inherit the parent's path; without a path property, the full path will not resolve correctly at runtime. Update the route type/validation to require path for such routes and add tests ensuring that a pathless_layout with cleanedPath provides a valid fullPath resolution.

Applied to files:

  • packages/router-generator/src/generator.ts
🧬 Code graph analysis (8)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx (9)
packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx (1)
  • Route (3-10)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx (8)
packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator.test.ts (1)
packages/router-generator/src/config.ts (1)
  • getConfig (89-170)
packages/router-generator/src/filesystem/physical/getRouteNodes.ts (2)
packages/router-generator/src/utils.ts (1)
  • unwrapBracketWrappedSegment (479-481)
packages/router-generator/src/types.ts (1)
  • FsRouteType (24-34)
packages/router-generator/src/filesystem/virtual/getRouteNodes.ts (1)
packages/router-generator/src/filesystem/physical/getRouteNodes.ts (1)
  • TokenRegexBundle (27-30)
packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx (1)
packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx (9)
packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx (1)
  • Route (3-10)
packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx (1)
  • Route (3-10)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx (1)
  • Route (3-5)
packages/router-generator/src/utils.ts (1)
packages/router-generator/src/config.ts (1)
  • TokenMatcher (20-20)
🪛 ast-grep (0.40.4)
packages/router-generator/src/filesystem/physical/getRouteNodes.ts

[warning] 262-262: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(/${stripSegment}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 264-264: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(/${stripSegment}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 302-302: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(/${updatedLastRouteSegment}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 308-308: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(/${indexTokenCandidate}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

packages/router-generator/src/utils.ts

[warning] 438-438: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${escapeRegExp(token)}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 439-439: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([./]${escapeRegExp(token)}[.])
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 444-444: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^(?:${token.source})$, token.flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 445-445: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([./](?:${token.source})[.], token.flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 451-451: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^(?:${token.regex})$, token.flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 452-452: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([./](?:${token.regex})[.], token.flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: Preview
🔇 Additional comments (26)
packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json (1)

1-4: LGTM! Well-structured test fixture for regex token validation.

The regex patterns correctly demonstrate the new feature, matching custom-named route files (e.g., home-page, main-layout) while preserving route behavior.

packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx (1)

1-5: LGTM! Standard route definition.

The route file correctly demonstrates a regular route file that works alongside the regex token feature for testing purposes.

packages/router-generator/tests/generator/virtual-config-file-named-export/tsr.config.json (1)

1-5: LGTM! Valid test configuration.

Standard virtual route config setup for testing purposes.

packages/router-generator/tests/generator/virtual-config-file-default-export/tsr.config.json (1)

1-5: LGTM! Valid test configuration.

Standard virtual route config setup for testing default export behavior.

docs/router/api/file-based-routing.md (1)

104-170: Excellent documentation of the new regex token feature!

The documentation is comprehensive and well-structured, covering:

  • JSON and inline configuration formats for both routeToken and indexToken
  • Practical filename examples demonstrating matching behavior
  • Important clarifications about entire segment matching
  • Escaping guidance for edge cases

The examples and notes effectively guide users in adopting this feature for custom file naming patterns.

docs/router/framework/react/routing/file-naming-conventions.md (1)

7-18: LGTM! Clear documentation of regex pattern support.

The updated table entries accurately describe the new capability for indexToken and routeToken to accept both strings and regex patterns, with appropriate links to the API documentation for detailed configuration options.

packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx (1)

1-5: LGTM! Clean test fixture for root route.

This test file correctly defines a root route using createFileRoute and will serve as an appropriate fixture for testing the regex token matching feature where index-page.tsx is matched by a custom indexToken pattern.

packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx (1)

1-5: LGTM! Correct index route definition.

The route correctly uses /dashboard/ with a trailing slash to represent an index route under the dashboard path. This appropriately tests the custom indexToken pattern where home-page replaces the default index token.

packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx (1)

1-10: LGTM! Proper layout route structure.

The layout route correctly imports and uses Outlet for nested route rendering, with the path /dashboard (without trailing slash) appropriately representing a parent layout route. This effectively tests the custom routeToken pattern where main-layout replaces the default route token.

packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx (1)

1-5: LGTM! Clean leaf route definition.

This route correctly defines a nested page under the dashboard path. The simple structure is appropriate for a test fixture validating the regex token matching functionality.

packages/router-generator/src/config.ts (3)

7-20: Well-structured token schema definitions.

The schema correctly supports all three token forms: plain strings, RegExp instances, and JSON regex objects (for config file serialization). The type exports make the API clear for consumers.


40-41: Token configuration update looks good.

The indexToken and routeToken fields now accept the flexible tokenMatcherSchema, with sensible string defaults maintaining backward compatibility.


102-111: Config merging order is correct.

The inline config properly overrides file config values. Parsing once after merging ensures defaults are applied correctly without file values being overwritten by inline defaults.

packages/router-generator/src/filesystem/physical/getRouteNodes.ts (2)

22-30: Clean interface for pre-compiled token regexes.

The TokenRegexBundle interface properly encapsulates the pre-compiled regexes, avoiding repeated regex compilation during route crawling. Good design for performance.


282-313: Verify whether layout routes with names matching the index token pattern are tested.

The test suite includes regex-tokens-inline and regex-tokens-json test cases that verify the generator with regex index and route tokens. These tests confirm that layout routes (e.g., dashboard.main-layout) and index routes (e.g., index-page, dashboard.home-page) are correctly generated. However, the specific edge case where a layout route's filename itself matches the index token pattern (e.g., a layout route named to match /[a-z]+-page/) is not explicitly covered by existing test snapshots. The current tests validate layout routes matching the routeToken pattern and index routes matching the indexToken pattern separately, but not the intersection of these conditions.

packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts (1)

1-104: Snapshot file - no review needed.

Based on learnings, test snapshot files in the router-generator tests directory are fixtures used to verify the generator's output and should be preserved as-is.

packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx (1)

1-10: Test fixture for regex token layout route.

This test file correctly demonstrates the main-layout token pattern matching for the /dashboard route with an <Outlet /> for nested routes. Aligns with the regex-tokens-json variant.

packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx (1)

1-5: Test fixture for regex token index route.

Correctly defines the root index route using the index-page naming pattern that should be matched by the regex indexToken configuration.

packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx (1)

1-5: Standard root route definition.

Follows the established pattern for root route files in the test suite.

packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx (1)

1-5: Test fixture for dashboard index route.

Correctly defines the dashboard index route at /dashboard/ using the home-page naming pattern for regex token matching.

packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx (1)

1-5: Looks good for a test fixture root route.

packages/router-generator/tests/generator.test.ts (1)

161-167: Inline RegExp token fixture looks good.

packages/router-generator/src/filesystem/virtual/getRouteNodes.ts (1)

42-88: TokenRegexBundle threading looks consistent.

Also applies to: 129-159

packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts (1)

1-121: Generated snapshot fixture — skipping review.

packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts (1)

1-121: Generated snapshot fixture — skipping review.

packages/router-generator/src/utils.ts (1)

475-481: No action needed. isBracketWrappedSegment and unwrapBracketWrappedSegment are only used within a constrained context where route paths are split by / into individual segments, preventing compound strings like "[a][b]". All callers validate bracket wrapping before unwrapping.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @packages/router-generator/tests/generator.test.ts:
- Around line 301-315: Update the test to use regexes that match
createTokenRegex's output for default string tokens by replacing the
non-capturing-group patterns passed to virtualGetRouteNodes with plain anchors —
use /^index$/ and /^route$/ (or generate them via createTokenRegex('index') and
createTokenRegex('route')) so the test aligns with how createTokenRegex produces
/^index$/ and /^route$/ for string tokens when invoking virtualGetRouteNodes.
🧹 Nitpick comments (2)
packages/router-generator/src/filesystem/physical/getRouteNodes.ts (2)

262-268: Escape regex special characters in path segments.

The stripSegment variable (derived from file paths) is used directly in RegExp constructor without escaping. While the risk is low since these come from filesystem paths with anchored patterns, it's safer to escape special regex characters.

🛡️ Proposed fix to escape regex special characters

Add an escape helper at the top of the file if not already imported:

+function escapeRegExpChars(s: string): string {
+  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+}

Then apply it to the segment:

         if (suffixToStrip || shouldStripRouteToken) {
           const stripSegment = suffixToStrip ?? lastRouteSegment
-          routePath = routePath.replace(new RegExp(`/${stripSegment}$`), '')
+          routePath = routePath.replace(new RegExp(`/${escapeRegExpChars(stripSegment)}$`), '')
           originalRoutePath = originalRoutePath.replace(
-            new RegExp(`/${stripSegment}$`),
+            new RegExp(`/${escapeRegExpChars(stripSegment)}$`),
             '',
           )
         }

301-312: Escape regex special characters in index token handling.

Similar to the suffix stripping logic, the updatedLastRouteSegment and indexTokenCandidate variables should be escaped before use in RegExp constructor.

🛡️ Proposed fix to escape regex special characters
             routePath =
               routePath.replace(
-                new RegExp(`/${updatedLastRouteSegment}$`),
+                new RegExp(`/${escapeRegExpChars(updatedLastRouteSegment)}$`),
                 '/',
               ) || (isLayoutRoute ? '' : '/')

             originalRoutePath =
               originalRoutePath.replace(
-                new RegExp(`/${indexTokenCandidate}$`),
+                new RegExp(`/${escapeRegExpChars(indexTokenCandidate)}$`),
                 '/',
               ) || (isLayoutRoute ? '' : '/')
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ece084f and 029f14a.

📒 Files selected for processing (24)
  • docs/router/api/file-based-routing.md
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/src/config.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/src/utils.ts
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • packages/router-generator/tests/generator/virtual-config-file-default-export/tsr.config.json
  • packages/router-generator/tests/generator/virtual-config-file-named-export/tsr.config.json
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/router-generator/tests/generator/virtual-config-file-named-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx
  • packages/router-generator/tests/generator/virtual-config-file-default-export/tsr.config.json
  • packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • packages/router-generator/src/generator.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
  • packages/router-generator/src/utils.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • packages/router-generator/src/generator.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
  • packages/router-generator/src/utils.ts
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

Use relative links to docs/ folder format (e.g., ./guide/data-loading) for internal documentation references

Files:

  • docs/router/api/file-based-routing.md
  • docs/router/framework/react/routing/file-naming-conventions.md
🧠 Learnings (12)
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • packages/router-generator/src/generator.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • packages/router-generator/src/utils.ts
📚 Learning: 2025-12-17T02:17:47.423Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:47.423Z
Learning: In packages/router-generator/src/generator.ts, enforce that pathless_layout routes with a cleanedPath must have a path property. This is required because child routes inherit the parent's path; without a path property, the full path will not resolve correctly at runtime. Update the route type/validation to require path for such routes and add tests ensuring that a pathless_layout with cleanedPath provides a valid fullPath resolution.

Applied to files:

  • packages/router-generator/src/generator.ts
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.

Applied to files:

  • packages/router-generator/src/generator.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • packages/router-generator/src/utils.ts
📚 Learning: 2025-12-21T12:52:35.231Z
Learnt from: Sheraff
Repo: TanStack/router PR: 6171
File: packages/router-core/src/new-process-route-tree.ts:898-898
Timestamp: 2025-12-21T12:52:35.231Z
Learning: In `packages/router-core/src/new-process-route-tree.ts`, the matching logic intentionally allows paths without trailing slashes to match index routes with trailing slashes (e.g., `/a` can match `/a/` route), but not vice-versa (e.g., `/a/` cannot match `/a` layout route). This is implemented via the condition `!pathIsIndex || node.kind === SEGMENT_TYPE_INDEX` and is a deliberate design decision to provide better UX by being permissive with missing trailing slashes.

Applied to files:

  • packages/router-generator/src/generator.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • docs/router/api/file-based-routing.md
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
  • packages/router-generator/src/utils.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • packages/router-generator/src/generator.ts
  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • docs/router/api/file-based-routing.md
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json
  • packages/router-generator/src/utils.ts
📚 Learning: 2025-12-17T02:17:55.086Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:55.086Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.

Applied to files:

  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • docs/router/api/file-based-routing.md
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/src/filesystem/virtual/getRouteNodes.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
  • packages/router-generator/src/utils.ts
📚 Learning: 2025-09-22T00:56:49.237Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5182
File: e2e/react-router/basic-file-based/src/routes/non-nested/named/$baz_.bar.tsx:3-5
Timestamp: 2025-09-22T00:56:49.237Z
Learning: In TanStack Router, underscores are intentionally stripped from route segments (e.g., `$baz_` becomes `baz` in generated types) but should be preserved in base path segments. This is the correct behavior as of the fix in PR #5182.

Applied to files:

  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
📚 Learning: 2025-10-01T18:30:26.591Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.

Applied to files:

  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
  • packages/router-generator/src/utils.ts
📚 Learning: 2025-09-22T00:56:53.426Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5182
File: e2e/react-router/basic-file-based/tests/non-nested-paths.spec.ts:167-172
Timestamp: 2025-09-22T00:56:53.426Z
Learning: In TanStack Router, underscores are intentionally stripped from route segments during path parsing, but preserved in base path segments. This is the expected behavior implemented in PR #5182.

Applied to files:

  • packages/router-generator/src/filesystem/physical/getRouteNodes.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions

Applied to files:

  • docs/router/api/file-based-routing.md
  • docs/router/framework/react/routing/file-naming-conventions.md
  • packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx
  • packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts
📚 Learning: 2025-09-28T21:41:45.233Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5284
File: e2e/react-start/basic/server.js:50-0
Timestamp: 2025-09-28T21:41:45.233Z
Learning: In Express v5, catch-all routes must use named wildcards. Use `/*splat` to match everything except root path, or `/{*splat}` (with braces) to match including root path. The old `*` syntax is not allowed and will cause "Missing parameter name" errors. This breaking change requires explicit naming of wildcard parameters.

Applied to files:

  • docs/router/api/file-based-routing.md
  • docs/router/framework/react/routing/file-naming-conventions.md
📚 Learning: 2025-10-14T18:59:33.990Z
Learnt from: FatahChan
Repo: TanStack/router PR: 5475
File: e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx:8-0
Timestamp: 2025-10-14T18:59:33.990Z
Learning: In TanStack Router e2e test files, when a route parameter is validated at the route level (e.g., using zod in validateSearch or param validation), switch statements on that parameter do not require a default case, as the validation ensures only expected values will reach the switch.

Applied to files:

  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts
  • packages/router-generator/src/config.ts
  • packages/router-generator/src/utils.ts
🧬 Code graph analysis (6)
packages/router-generator/src/generator.ts (1)
packages/router-generator/src/utils.ts (2)
  • createTokenRegex (429-483)
  • multiSortBy (90-134)
packages/router-generator/src/filesystem/physical/getRouteNodes.ts (2)
packages/router-generator/src/utils.ts (1)
  • unwrapBracketWrappedSegment (489-491)
packages/router-generator/src/types.ts (1)
  • FsRouteType (24-34)
packages/router-generator/src/filesystem/virtual/getRouteNodes.ts (1)
packages/router-generator/src/filesystem/physical/getRouteNodes.ts (1)
  • TokenRegexBundle (27-30)
packages/router-generator/tests/generator.test.ts (1)
packages/router-generator/src/config.ts (1)
  • getConfig (89-170)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx (8)
packages/router-generator/tests/generator/regex-tokens-inline/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.home-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-inline/routes/dashboard.main-layout.tsx (1)
  • Route (3-10)
packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/__root.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.home-page.tsx (1)
  • Route (3-5)
packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.main-layout.tsx (1)
  • Route (3-10)
packages/router-generator/tests/generator/regex-tokens-json/routes/index-page.tsx (1)
  • Route (3-5)
packages/router-generator/src/utils.ts (1)
packages/router-generator/src/config.ts (1)
  • TokenMatcher (20-20)
🪛 ast-grep (0.40.4)
packages/router-generator/src/filesystem/physical/getRouteNodes.ts

[warning] 262-262: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(/${stripSegment}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 264-264: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(/${stripSegment}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 302-302: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(/${updatedLastRouteSegment}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 308-308: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(/${indexTokenCandidate}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

packages/router-generator/src/utils.ts

[warning] 446-446: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${escapeRegExp(token)}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 447-447: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([./]${escapeRegExp(token)}[.])
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 453-453: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^(?:${token.source})$, flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 454-454: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([./](?:${token.source})[.], flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 461-461: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^(?:${token.regex})$, flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 462-462: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([./](?:${token.regex})[.], flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: Preview
🔇 Additional comments (25)
packages/router-generator/tests/generator/regex-tokens-json/routeTree.snapshot.ts (1)

1-121: LGTM - Valid test fixture for JSON regex tokens feature.

This snapshot correctly captures the expected generator output when using JSON-style regex tokens for indexToken and routeToken. The route naming pattern (index-page, main-layout, home-page) demonstrates the regex token matching is working as intended, and the structure aligns with the standard TanStack Router generated file pattern.

Based on learnings, test snapshot files in this directory are fixtures used to verify the generator's output and are intentionally preserved as-is.

packages/router-generator/tests/generator/regex-tokens-json/routes/dashboard.settings.tsx (1)

1-5: LGTM! Test fixture follows established pattern.

This test route file correctly implements the file-based routing pattern for the regex-tokens-json test case. The route path '/dashboard/settings' appropriately maps from the filename 'dashboard.settings.tsx', and the implementation matches the structure of other test fixtures in this directory.

packages/router-generator/tests/generator/regex-tokens-json/tsr.config.json (1)

1-4: Test configuration is correct; patterns are automatically anchored by the generator.

The configuration correctly uses the JSON format for regex tokens. The original concern about unanchored patterns is resolved by the generator's implementation: when processing regex tokens from the config object, the generator automatically wraps patterns with anchors based on context (line 462-463 in packages/router-generator/src/utils.ts).

For segment matching, patterns are wrapped as ^(?:${token.regex})$, ensuring exact matching. For filename matching, they're wrapped as [./](?:${token.regex})[.]. The test configuration is correct as-is—users provide clean patterns, and the generator handles the context-specific anchoring internally.

docs/router/framework/react/routing/file-naming-conventions.md (1)

7-18: LGTM! Documentation accurately reflects the regex support feature.

The table updates clearly communicate that both indexToken and routeToken now support strings and regex patterns, with appropriate references to the detailed API documentation.

packages/router-generator/tests/generator/regex-tokens-inline/routes/index-page.tsx (1)

1-5: LGTM! Test route file follows standard patterns.

The route file correctly uses createFileRoute API and provides a simple component for testing regex token functionality.

packages/router-generator/src/filesystem/physical/getRouteNodes.ts (2)

22-30: LGTM! Well-designed abstraction for token regex handling.

The TokenRegexBundle interface provides a clean way to pass pre-compiled token regexes through the route discovery process, avoiding repeated regex compilation.


174-174: LGTM! Function signature correctly propagates token regexes.

The updated signature ensures consistent token handling across route meta evaluation.

docs/router/api/file-based-routing.md (2)

104-131: Excellent documentation for regex pattern support!

The section provides clear examples for both JSON config and inline code usage, with helpful notes about full-segment matching behavior. The examples are practical and easy to understand.


145-169: LGTM! Clear and comprehensive indexToken regex documentation.

The documentation parallels the routeToken section effectively and includes important guidance on escaping regex tokens. This will help users understand the feature quickly.

packages/router-generator/src/utils.ts (3)

421-427: LGTM! Good defensive measure against stateful regex behavior.

Removing the 'g' and 'y' flags prevents issues with lastIndex state when using test() or exec() methods.


485-491: LGTM! Clean helper functions for bracket escaping.

These utilities provide a clear API for detecting and unwrapping bracket-escaped segments, supporting the new escaping mechanism.


429-483: LGTM! Comprehensive token regex creation with good error handling.

The function handles all three token forms (string, RegExp, JSON object) with appropriate validation and error messages. String tokens are properly escaped via escapeRegExp(), and the try-catch handles SyntaxErrors effectively.

Note: User-provided regex patterns in config files could potentially cause ReDoS (Regular Expression Denial of Service) with complex patterns containing nested quantifiers or excessive backtracking—for example, patterns like (a+)+b can cause exponential backtracking. While this is a config-time concern (not runtime) and developers typically control config files, regex complexity is not validated here. If you want additional safety, libraries like safe-regex or recheck can detect potentially problematic patterns, though this is optional since route generation happens at build time with developer-controlled configuration.

packages/router-generator/tests/generator.test.ts (2)

44-64: LGTM: Config directory detection logic is well-structured.

The setup now properly detects whether a tsr.config.json exists in the test folder and passes the directory to getConfig, enabling tests to use file-based configurations. This aligns with the updated getConfig signature that accepts an optional configDirectory parameter.


161-167: Good test case for inline RegExp tokens.

The inline RegExp patterns for indexToken (/[a-z]+-page/) and routeToken (/[a-z]+-layout/) effectively test the new regex token functionality, matching patterns like "index-page" or "protected-layout".

packages/router-generator/src/config.ts (3)

7-20: Well-designed schema for flexible token matching.

The tokenMatcherSchema correctly supports three forms: plain strings, RegExp instances, and JSON regex objects ({ regex, flags }). This enables both programmatic and JSON-based configuration. The type exports (TokenMatcherJson, TokenMatcher) provide good type safety for consumers.


102-111: Improved config merging preserves file-based defaults.

The updated merge logic correctly spreads fileConfigRaw first, then inlineConfig, ensuring inline values override file values. Parsing the merged result once applies schema defaults only to unset fields, fixing the previous behavior where inline defaults could override file config values.


208-231: Consider normalizing mixed-type comparisons.

The areTokensEqual function returns false for mixed types (e.g., string vs RegExp with the same pattern). This is intentional but worth documenting. A string "index" and RegExp(/index/) would not be considered equal even though they match the same text.

This behavior is reasonable since the types have different semantics (exact match vs pattern match), but if cross-type equivalence is ever needed, this would need updating.

packages/router-generator/src/filesystem/virtual/getRouteNodes.ts (2)

42-54: Token regex propagation is correctly implemented.

The tokenRegexes parameter is properly threaded through the virtual route node generation, ensuring consistent token matching behavior across both virtual and physical route discovery paths.


159-162: Good fix for physical directory accumulation.

The change correctly accumulates both the direct physical directory (resolve(fullDir, node.directory)) and any nested physical directories returned from getRouteNodesPhysical. This ensures the generator tracks all mounted physical directories for file relevance checks.

packages/router-generator/src/generator.ts (4)

195-214: Excellent documentation for the dual regex strategy.

The comment clearly explains why two regex types are needed:

  1. Filename regexes: Match tokens within full file paths (bounded by path separators/dots)
  2. Segment regexes: Match tokens against isolated route segments (exact match)

This distinction prevents false positives and ensures correct behavior in different contexts.


229-241: LGTM: Pre-compiled regexes in constructor.

Creating all token regexes once in the constructor is efficient and ensures consistent regex instances are reused throughout route processing.


584-597: Smart optimization for config override scenario.

The logic correctly reuses the pre-compiled indexTokenSegmentRegex when the config hasn't been overridden, and only creates a new regex when a different indexToken is provided via opts.config. This handles plugin scenarios that may override config while maintaining efficiency for the common case.


393-401: Sorting logic correctly uses filename-level regexes.

The multiSortBy accessors now use indexTokenFilenameRegex and routeTokenFilenameRegex to detect tokens within file paths. This is the correct choice for path-based sorting since file paths contain dots and separators.

packages/router-generator/tests/generator/virtual-physical-layout-and-index/routeTree.snapshot.ts (1)

1-104: Snapshot file - no review needed.

Based on learnings, test snapshot files in the router-generator tests directory are fixtures used to verify the generator's output and should be preserved as-is.

packages/router-generator/tests/generator/regex-tokens-inline/routeTree.snapshot.ts (1)

1-121: New snapshot for regex-tokens-inline test.

This snapshot file correctly demonstrates the generated route tree when using inline RegExp tokens. The structure shows proper handling of routes named with the -page and -layout patterns (e.g., index-page, main-layout).

Based on learnings, test snapshot files are fixtures and should be preserved as-is.

Comment on lines +301 to +315
it('physical() mount returns absolute physicalDirectories', async () => {
const folderName = 'virtual-physical-no-prefix'
const dir = makeFolderDir(folderName)
const config = await setupConfig(folderName)

const { physicalDirectories } = await virtualGetRouteNodes(config, dir, {
indexTokenSegmentRegex: /^(?:index)$/,
routeTokenSegmentRegex: /^(?:route)$/,
})

expect(physicalDirectories.length).toBeGreaterThan(0)
physicalDirectories.forEach((physicalDir) => {
expect(path.isAbsolute(physicalDir)).toBe(true)
})
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find createTokenRegex definition
rg -n "createTokenRegex" --type ts --type tsx -A5 packages/router-generator/src/

Repository: TanStack/router

Length of output: 86


🏁 Script executed:

#!/bin/bash
# Check the test file for context
cat -n packages/router-generator/tests/generator.test.ts | sed -n '301,315p'

Repository: TanStack/router

Length of output: 734


🏁 Script executed:

#!/bin/bash
# Also search for where indexTokenSegmentRegex and routeTokenSegmentRegex are used elsewhere
rg -n "indexTokenSegmentRegex|routeTokenSegmentRegex" --type ts --type tsx packages/router-generator/ | head -20

Repository: TanStack/router

Length of output: 86


🏁 Script executed:

#!/bin/bash
# Search for createTokenRegex without file type restrictions
rg -n "createTokenRegex" packages/router-generator/src/ -A5

Repository: TanStack/router

Length of output: 3507


🏁 Script executed:

#!/bin/bash
# List TypeScript/JS files in utils directory
fd . packages/router-generator/src/ -e ts -e js | head -20

Repository: TanStack/router

Length of output: 860


🏁 Script executed:

#!/bin/bash
# Check what virtualGetRouteNodes expects as parameters
rg -n "virtualGetRouteNodes" packages/router-generator/ -B2 -A8 | head -50

Repository: TanStack/router

Length of output: 3958


🏁 Script executed:

#!/bin/bash
# Get the full createTokenRegex implementation
cat -n packages/router-generator/src/utils.ts | sed -n '429,480p'

Repository: TanStack/router

Length of output: 2174


🏁 Script executed:

#!/bin/bash
# Also check what the default config tokens are
rg -n "indexToken|routeToken" packages/router-generator/src/config.ts -B2 -A2 | head -40

Repository: TanStack/router

Length of output: 671


🏁 Script executed:

#!/bin/bash
# Check if there's documentation or setup for this test
cat -n packages/router-generator/tests/generator.test.ts | sed -n '285,320p'

Repository: TanStack/router

Length of output: 1416


🏁 Script executed:

#!/bin/bash
# Look for setupConfig function to understand test setup
rg -n "function setupConfig|const setupConfig" packages/router-generator/tests/ -A10

Repository: TanStack/router

Length of output: 2108


🏁 Script executed:

#!/bin/bash
# Check if there are other tests using these regex patterns
rg -n "indexTokenSegmentRegex|routeTokenSegmentRegex" packages/router-generator/tests/ -B2 -A2

Repository: TanStack/router

Length of output: 559


🏁 Script executed:

#!/bin/bash
# Check the virtualGetRouteNodes function signature and what it expects
cat -n packages/router-generator/src/filesystem/virtual/getRouteNodes.ts | head -50

Repository: TanStack/router

Length of output: 1685


🏁 Script executed:

#!/bin/bash
# Also check if there's test documentation or comments explaining this test
cat -n packages/router-generator/tests/generator.test.ts | sed -n '295,310p'

Repository: TanStack/router

Length of output: 623


🏁 Script executed:

#!/bin/bash
# Get more of the virtualGetRouteNodes signature and type definition
cat -n packages/router-generator/src/filesystem/virtual/getRouteNodes.ts | sed -n '42,70p'

Repository: TanStack/router

Length of output: 1096


🏁 Script executed:

#!/bin/bash
# Look for TokenRegexBundle type definition
rg -n "type TokenRegexBundle" packages/router-generator/src/

Repository: TanStack/router

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Check the physical getRouteNodes to understand the expected parameter structure
cat -n packages/router-generator/src/filesystem/physical/getRouteNodes.ts | head -100

Repository: TanStack/router

Length of output: 3801


🏁 Script executed:

#!/bin/bash
# Check what config setupConfig produces for indexToken and routeToken
cat -n packages/router-generator/tests/generator.test.ts | sed -n '44,65p'

Repository: TanStack/router

Length of output: 779


🏁 Script executed:

#!/bin/bash
# Check if the 'virtual-physical-no-prefix' test folder has a tsr.config.json
find packages/router-generator/tests/generator/virtual-physical-no-prefix -name "*.json" -o -name "*.ts" | head -20

Repository: TanStack/router

Length of output: 313


🏁 Script executed:

#!/bin/bash
# Check the config for this test folder
cat packages/router-generator/tests/generator/virtual-physical-no-prefix/tsr.config.json

Repository: TanStack/router

Length of output: 179


🏁 Script executed:

#!/bin/bash
# Also verify what getConfig does with defaults
cat -n packages/router-generator/src/config.ts | sed -n '1,80p'

Repository: TanStack/router

Length of output: 3420


🏁 Script executed:

#!/bin/bash
# Let's verify the exact regex output createTokenRegex produces by checking escapeRegExp
rg -n "function escapeRegExp|const escapeRegExp" packages/router-generator/src/utils.ts -A5

Repository: TanStack/router

Length of output: 271


Update hardcoded regex patterns to match createTokenRegex output for default string tokens.

The test passes hardcoded regex patterns with non-capturing groups (/^(?:index)$/ and /^(?:route)$/) to virtualGetRouteNodes. However, createTokenRegex with default string tokens "index" and "route" produces /^index$/ and /^route$/ without the non-capturing groups. Non-capturing groups are only added for RegExp token types, not string tokens. While these patterns are functionally equivalent, align them with the actual output of createTokenRegex for consistency.

🤖 Prompt for AI Agents
In @packages/router-generator/tests/generator.test.ts around lines 301 - 315,
Update the test to use regexes that match createTokenRegex's output for default
string tokens by replacing the non-capturing-group patterns passed to
virtualGetRouteNodes with plain anchors — use /^index$/ and /^route$/ (or
generate them via createTokenRegex('index') and createTokenRegex('route')) so
the test aligns with how createTokenRegex produces /^index$/ and /^route$/ for
string tokens when invoking virtualGetRouteNodes.

Copy link
Member

@SeanCassiere SeanCassiere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Only question is whether we'll need to support that Regex.index=0 trick at some point 🤔. We can always fix forward is needed.

@schiller-manuel
Copy link
Contributor Author

shouldnt be stateful, see #6354 (comment)
this is applied

@schiller-manuel schiller-manuel merged commit bd40352 into main Jan 11, 2026
6 checks passed
@schiller-manuel schiller-manuel deleted the regex-token branch January 11, 2026 11:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Everything documentation related package: router-generator

Projects

None yet

Development

Successfully merging this pull request may close these issues.

routeToken no longer accepts RegExp-like string value as of @tanstack/[email protected]

3 participants